﻿using mvcForum.Core;
using mvcForum.Core.Interfaces.Data;
using mvcForum.Core.Specifications;
using mvcForum.Web.Areas.ForumAdmin.ViewModels.List;
using mvcForum.Web.Controllers;
using mvcForum.Web.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using AccessMaskVM = mvcForum.Web.Areas.ForumAPI.ViewModels.AccessMask;
using BoardLight = mvcForum.Web.Areas.ForumAPI.ViewModels.BoardLight;
using BoardVM = mvcForum.Web.Areas.ForumAPI.ViewModels.Board;
using CategoryLight = mvcForum.Web.Areas.ForumAPI.ViewModels.CategoryLight;

namespace mvcForum.Web.Areas.ForumAPI.Controllers {

	public class BoardController : BaseAPIController {

		/// <summary>
		/// Create a new board on the forum solution using the given settings.
		/// </summary>
		/// <param name="model">The properties of the new board.</param>
		/// <param name="mode">API mode.</param>
		/// <returns></returns>
		[HttpPost]
		[Authorize(Roles = Constants.Roles.SolutionAdmin)]
		public ActionResult Create(BoardVM model, String mode) {
			// TODO:
			Board board = new Board {
				Name = model.Name,
				Description = String.IsNullOrWhiteSpace(model.Description) ? "" : model.Description,
				Disabled = false
			};

			this.GetRepository<Board>().Create(board);
			this.Context.SaveChanges();

			return new HttpStatusCodeResult(200);
		}

		/// <summary>
		/// Read the board with the given Id.
		/// </summary>
		/// <param name="id">Id of the required board.</param>
		/// <param name="mode">API mode.</param>
		/// <returns>Data containing the requested board.</returns>
		public ActionResult Read(Int32 id, String mode) {
			// TODO: Access!
			Board board = this.GetRepository<Board>().Read(id);
			return this.CustomJson(new BoardVM {
				Id = board.Id,
				Name = board.Name,
				Disabled = board.Disabled,
				Description = board.Description
			});
		}

		[HttpPost]
		[Authorize(Roles = Constants.Roles.Combined)]
		public ActionResult Update(BoardVM model, String mode) {
			if (ModelState.IsValid) {
				Board board = this.GetRepository<Board>().Read(model.Id);
				// TODO: Access!!

				board.Name = model.Name;
				board.Description = model.Description;

				this.Context.SaveChanges();

				return new HttpStatusCodeResult(200);
			}

			return new HttpStatusCodeResult(500, ModelState.ErrorString());
		}

		/// <summary>
		/// Delete the board with the given Id.
		/// </summary>
		/// <param name="id">Id of the board.</param>
		/// <param name="mode">API mode.</param>
		/// <returns></returns>
		[Authorize(Roles = Constants.Roles.SolutionAdmin)]
		public ActionResult Delete(Int32 id, String mode) {
			IRepository<Board> boardRepo = this.GetRepository<Board>();

			Board board = boardRepo.Read(id);
			// TODO: Delete categories, forums, topics, etc. etc.
			boardRepo.Delete(board);

			this.Context.SaveChanges();

			return new HttpStatusCodeResult(200);
		}

		public ActionResult List(Int32? id, String mode) {
			// TODO: Access!
			if (id.HasValue) {
				Board board = this.GetRepository<Board>().Read(id.Value);
				return this.CustomJson(new { Categories = board.Categories.Select(c => new CategoryLight { Id = c.Id, Name = c.Name, SortOrder = c.SortOrder, ApiUrl = Url.Action("read", "category", new { area = "forumapi", mode = "json", id = c.Id }) }).OrderBy(c => c.SortOrder) });
			}
			else {
				IEnumerable<Board> boards = this.GetRepository<Board>().ReadAll();
				return this.CustomJson(new { Boards = boards.Select(b => new BoardLight { Id = b.Id, Name = b.Name, ApiUrl = Url.Action("read", "board", new { area = "forumapi", mode = "json", id = b.Id }) }).OrderBy(b => b.Name) });
			}
		}

		[Authorize(Roles = Constants.Roles.Combined)]
		public ActionResult AccessMaskList(Int32 id, String mode) {
			// TODO: Access!
			Board board = this.GetRepository<Board>().Read(id);
			IEnumerable<AccessMask> masks = this.GetRepository<AccessMask>().ReadMany(new AccessMaskSpecifications.SpecificBoard(board));
			return this.CustomJson(new { AccessMasks = masks.Select(m => new AccessMaskVM { Id = m.Id, Name = m.Name, AccessFlag = m.AccessFlag, ApiUrl = Url.Action("read", "accessmask", new { area = "forumapi", mode = "json", id = m.Id }) }).OrderBy(m => m.Name) });
		}

		[Authorize(Roles = Constants.Roles.Combined)]
		public ActionResult Statistics(Int32 id, String mode) {
			ForumSettings setting = this.GetRepository<ForumSettings>().ReadOne(new ForumSettingsSpecifications.SpecificKey("InstallDate"));
			DateTime installDate = DateTime.Parse(setting.Value);

			Statistics stats = new Statistics {
				TopicCount = this.GetRepository<Topic>().ReadMany(new TopicSpecifications.Visible()).Count(),
				PostCount = this.GetRepository<Post>().ReadMany(new PostSpecifications.Visible()).Count(),
				AttachmentCount = this.GetRepository<Attachment>().ReadAll().Count(),
				UserCount = this.GetRepository<ForumUser>().ReadMany(new ForumUserSpecifications.NotDeleted()).Count(),
				AttachmentSize = this.GetRepository<Attachment>().ReadAll().Sum(a => a.Size),
				InstallDate = installDate,
				Days = DateTime.UtcNow.Subtract(installDate).Days,
				Version = this.GetType().Assembly.GetName().Version.ToString()
			};

			return this.CustomJson(stats);
		}
	}
}